import { isArray } from 'util';
import { exportDefault, titleCase, deepClone } from '@/util/formGenerator/index';
import ruleTrigger from './ruleTrigger';

const units = {
    KB: '1024',
    MB: '1024 / 1024',
    GB: '1024 / 1024 / 1024'
};
let confGlobal;
const inheritAttrs = {
    file: '',
    dialog: 'inheritAttrs: false,'
};

/**
 * 组装js 【入口函数】
 * @param {Object} formConfig 整个表单配置
 * @param {String} type 生成类型，文件或弹窗等
 */
export function makeUpJs(formConfig, type) {
    confGlobal = formConfig = deepClone(formConfig);
    const dataList = [];
    const ruleList = [];
    const optionsList = [];
    const propsList = [];
    const methodList = mixinMethod(type);
    const uploadVarList = [];
    const created = [];

    formConfig.fields.forEach((el) => {
        buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created);
    });

    const script = buildexport(
        formConfig,
        type,
        dataList.join('\n'),
        ruleList.join('\n'),
        optionsList.join('\n'),
        uploadVarList.join('\n'),
        propsList.join('\n'),
        methodList.join('\n'),
        created.join('\n')
    );
    confGlobal = null;
    return script;
}

// 构建组件属性
function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
    const config = scheme.__config__;
    const slot = scheme.__slot__;
    buildData(scheme, dataList);
    buildRules(scheme, ruleList);

    // 特殊处理options属性
    if (scheme.options || (slot && slot.options && slot.options.length)) {
        buildOptions(scheme, optionsList);
        if (config.dataType === 'dynamic') {
            const model = `${scheme.__vModel__}Options`;
            const options = titleCase(model);
            const methodName = `get${options}`;
            buildOptionMethod(methodName, model, methodList, scheme);
            callInCreated(methodName, created);
        }
    }

    // 处理props
    if (scheme.props && scheme.props.props) {
        buildProps(scheme, propsList);
    }

    // 处理el-upload的action
    if (scheme.action && config.tag === 'el-upload') {
        uploadVarList.push(
            `${scheme.__vModel__}Action: '${scheme.action}',
      ${scheme.__vModel__}fileList: [],`
        );
        methodList.push(buildBeforeUpload(scheme));
        // 非自动上传时，生成手动上传的函数
        if (!scheme['auto-upload']) {
            methodList.push(buildSubmitUpload(scheme));
        }
    }

    // 构建子级组件属性
    if (config.children) {
        config.children.forEach((item) => {
            buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created);
        });
    }
}

// 在Created调用函数
function callInCreated(methodName, created) {
    created.push(`this.${methodName}()`);
}

// 混入处理函数
function mixinMethod(type) {
    const list = [];
    const minxins = {
        file: confGlobal.formBtns
            ? {
                  submitForm: `submitForm() {
        this.$refs['${confGlobal.formRef}'].validate(valid => {
          if(!valid) return
          // TODO 提交表单
        })
      },`,
                  resetForm: `resetForm() {
        this.$refs['${confGlobal.formRef}'].resetFields()
      },`
              }
            : null,
        dialog: {
            onOpen: 'onOpen() {},',
            onClose: `onClose() {
        this.$refs['${confGlobal.formRef}'].resetFields()
      },`,
            close: `close() {
        this.$emit('update:visible', false)
      },`,
            handelConfirm: `handelConfirm() {
        this.$refs['${confGlobal.formRef}'].validate(valid => {
          if(!valid) return
          this.close()
        })
      },`
        }
    };

    const methods = minxins[type];
    if (methods) {
        Object.keys(methods).forEach((key) => {
            list.push(methods[key]);
        });
    }

    return list;
}

// 构建data
function buildData(scheme, dataList) {
    const config = scheme.__config__;
    if (scheme.__vModel__ === undefined) return;
    const defaultValue = JSON.stringify(config.defaultValue);
    dataList.push(`${scheme.__vModel__}: ${defaultValue},`);
}

// 构建校验规则
function buildRules(scheme, ruleList) {
    const config = scheme.__config__;
    if (scheme.__vModel__ === undefined) return;
    const rules = [];
    if (ruleTrigger[config.tag]) {
        if (config.required) {
            const type = isArray(config.defaultValue) ? "type: 'array'," : '';
            let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder;
            if (message === undefined) message = `${config.label}不能为空`;
            rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`);
        }
        if (config.regList && isArray(config.regList)) {
            config.regList.forEach((item) => {
                if (item.pattern) {
                    rules.push(
                        `{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${
                            ruleTrigger[config.tag]
                        }' }`
                    );
                }
            });
        }
        ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`);
    }
}

// 构建options
function buildOptions(scheme, optionsList) {
    if (scheme.__vModel__ === undefined) return;
    // el-cascader直接有options属性，其他组件都是定义在slot中，所以有两处判断
    let { options } = scheme;
    if (!options) options = scheme.__slot__.options;
    if (scheme.__config__.dataType === 'dynamic') {
        options = [];
    }
    const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`;
    optionsList.push(str);
}

function buildProps(scheme, propsList) {
    const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},`;
    propsList.push(str);
}

// el-upload的BeforeUpload
function buildBeforeUpload(scheme) {
    const config = scheme.__config__;
    const unitNum = units[config.sizeUnit];
    let rightSizeCode = '';
    let acceptCode = '';
    const returnList = [];
    if (config.fileSize) {
        rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
    if(!isRightSize){
      this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
    }`;
        returnList.push('isRightSize');
    }
    if (scheme.accept) {
        acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
    if(!isAccept){
      this.$message.error('应该选择${scheme.accept}类型的文件')
    }`;
        returnList.push('isAccept');
    }
    const str = `${scheme.__vModel__}BeforeUpload(file) {
    ${rightSizeCode}
    ${acceptCode}
    return ${returnList.join('&&')}
  },`;
    return returnList.length ? str : '';
}

// el-upload的submit
function buildSubmitUpload(scheme) {
    const str = `submitUpload() {
    this.$refs['${scheme.__vModel__}'].submit()
  },`;
    return str;
}

function buildOptionMethod(methodName, model, methodList, scheme) {
    const config = scheme.__config__;
    const str = `${methodName}() {
    // 注意：this.$axios是通过Vue.prototype.$axios = axios挂载产生的
    this.$axios({
      method: '${config.method}',
      url: '${config.url}'
    }).then(resp => {
      var { data } = resp
      this.${model} = data.${config.dataPath}
    })
  },`;
    methodList.push(str);
}

// js整体拼接
function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
    const str = `${exportDefault}{
  ${inheritAttrs[type]}
  components: {},
  props: [],
  data () {
    return {
      ${conf.formModel}: {
        ${data}
      },
      ${conf.formRules}: {
        ${rules}
      },
      ${uploadVar}
      ${selectOptions}
      ${props}
    }
  },
  computed: {},
  watch: {},
  created () {
    ${created}
  },
  mounted () {},
  methods: {
    ${methods}
  }
}`;
    return str;
}
